//
// Created by test on 23-3-7.
//
#include<time.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<stdio.h>
#include<pthread.h>
#include<sys/epoll.h>
#include<fcntl.h>
#include<errno.h>
#define BUF_SIZE 64
class tw_timer;
struct client_data{
    sockaddr_in address;
    int sockfd;
    char buf[BUF_SIZE];
    tw_timer* timer;
};
class tw_timer{
public:
    int rotation;
    int time_slot;
    void (*cb_func)(client_data*);
    client_data* user_data;
    tw_timer* next;
    tw_timer* prev;
    tw_timer(int rot,int ts):next(NULL),prev(NULL),rotation(rot),time_slot(ts){}

};
class time_wheel{
private:
    static const int N=60;
    static const int SI=1;
    tw_timer* slots[N];
    int cur_slot;
public:
    time_wheel():cur_slot(0){
        for(int i=0;i<N;i++){
            slots[i]=NULL;
        }
    }
    ~time_wheel(){
        for(int i=0;i<N;i++){
            tw_timer* tmp=slots[i];
            while(tmp!=NULL){
                slots[i]=tmp->next;
                delete tmp;
                tmp=slots[i];
            }
        }
    }
    tw_timer* add_timer(int timeout){
        if(timeout<0){
            return NULL;
        }
        int ticks=0;
        if(timeout<SI){
            ticks=1;
        }
        else{
            ticks=timeout/SI;
        }
        int rotation=ticks/N;
        int ts=(ticks+cur_slot)%N;
        tw_timer* timer=new tw_timer(rotation,ts);
        if(slots[ts]==NULL){
            slots[ts]=timer;
        }
        else{
            timer->next=slots[ts];
            slots[ts]->prev=timer;
            slots[ts]=timer;
        }
        return timer;
    }
    void del_timer(tw_timer* timer){
        if(timer==NULL){
            return;
        }
        int ts=timer->time_slot;
        if(timer==slots[ts]){
            slots[ts]=slots[ts];
            slots[ts]->prev=NULL;
            delete timer;
        }
        else{
            timer->prev->next=timer->next;
            if(timer->next) timer->next->prev=timer->prev;
            delete timer;
        }
    }
    void tick(){
        tw_timer* tmp=slots[cur_slot];
        while(tmp){
            if(tmp->rotation>0){
                tmp->rotation--;
                tmp=tmp->next;
            }
            else{
                tmp->cb_func(tmp->user_data);
                del_timer(tmp);
            }
        }
        cur_slot=++cur_slot%N;
    }
};